package com.z.redis.util;

import static java.nio.charset.StandardCharsets.UTF_8;
/**
 * @author z
 * Redis 键值编码、网络传输或序列化
 */
public class Format {
    // 64进制自定义字符集 将长整型数值压缩成短字符串
    static final  char[] EFNETBytes =new char[]{'0','1','2','3','4','5','6','7','8','9',
            'a','b','c','d','e','f','g','h','i','j','k','l',
            'm','n','o','p','q','r','s','t','u','v','w','x','y','z',
            'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V',
            'W','X','Y','Z','$','~'};
    // 36进制字符集
    static final byte[] digits = new byte[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
    // 优化数值转化字符串的性能 避免重复计算十位和个位 在getchar()方法中快速填充数字字符
    static final byte[] DigitTens = new byte[]{'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '6', '6', '6', '6', '6', '6', '6', '6', '6', '6', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '8', '8', '8', '8', '8', '8', '8', '8', '8', '8', '9', '9', '9', '9', '9', '9', '9', '9', '9', '9'};
    static final byte[] DigitOnes = new byte[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};

    public static int uint32(long z){
        return (int) (z & 0xFFFFFFFFL); // 将long转为无符号的32位整数
    }

    public static int uintNBit(long z,int n){
        return (int) (z & ((1L << n) - 1)); // 保留数值的低n位
    }

    public static String digits(int val, int digits){ // 将数字转为定长64进制字符串 生成更紧凑的Redis键名
        char[] buf = new char[digits];
        do {
            buf[--digits] = EFNETBytes[val & 63]; // 取低6位
            val >>>= 6;
        }while(digits>0);
        return new String(buf);
    }

    // 处理客户端命令中的数字参数 (比如Set key100 中的100)
    public static long parseLong(byte[] content, int radix) throws NumberFormatException {
        /*
        * WARNING 此方法可能在虚拟机初始化过程中被早期调用
        * 在IntegerCache初始化之前。一定要小心不要使用valueOf方法
         */
        if (content == null) {
            throw new NumberFormatException("null");
        }

        if (radix < Character.MIN_RADIX) {
            throw new NumberFormatException("radix " + radix +
                    " less than Character.MIN_RADIX");
        }

        if (radix > Character.MAX_RADIX) {
            throw new NumberFormatException("radix " + radix +
                    " greater than Character.MAX_RADIX");
        }

        long result = 0;
        boolean negative = false;
        int i = 0, len = content.length;
        int limit = -Integer.MAX_VALUE;
        int multmin;
        int digit;

        if (len > 0) {
            byte firstChar = content[0];
            if (firstChar < '0') {
                if (firstChar == '-') {
                    negative = true;
                    limit = Integer.MIN_VALUE;
                } else if (firstChar != '+') {
                    throw new NumberFormatException();
                }

                if (len == 1) // Cannot have lone "+" or "-"
                {
                    throw new NumberFormatException();
                }
                i++;
            }
            multmin = limit / radix;
            while (i < len) {
                // Accumulating negatively avoids surprises near MAX_VALUE
                digit = Character.digit(content[i++],radix);
                if (digit < 0) {
                    throw new NumberFormatException();
                }
                if (result < multmin) {
                    throw new NumberFormatException();
                }
                result *= radix;
                if (result < limit + digit) {
                    throw new NumberFormatException();
                }
                result -= digit;
            }
        } else {
            throw new NumberFormatException();
        }
        return negative ? result : -result;
    }

    static int stringSize(long value){ // 计算long的位数 如果超过19位按19算
        long temp=10L;
        for(int i=1;i<19;i++){
            if(temp>value){
                return i;
            }
            temp*=10L;
        }
        return 19;
    }

    public static byte[] toByteArray(long value) {
        if(value == Long.MIN_VALUE){
            return "-9223372036854775808".getBytes(UTF_8); // 特殊处理
        } else{
            int size = value < 0? stringSize(-value)+1 : stringSize(value); // value需要的数组大小
            byte[] arr = new byte[size];
            getChars(value,size,arr); // 高效填充字符
            return arr;
        }
    }

    static void getChars(long value,int size,byte[] buf){
        // 高性能数值转字符串的算法
        int index=size;
        byte var = 0; // 符号位 正数是0 负数是45
        if(value < 0L){
            var = 45;
            value = -value;
        }

        // 处理大数
        int digitOnesIndex;
        while(value > Integer.MAX_VALUE){ // 当value超过32位整型最大值
            long tmp = value / 100; // 得到除以100的高位部分
            // 计算余数：value-(tmp*100)
            // 等效于(tmp << 6)+(tmp << 5)+(tmp << 2)=var4 * 64 + var4 * 32 + var4 * 4 = var4 * 100
            digitOnesIndex = (int)(value - ((tmp << 6)+(tmp << 5)+(tmp << 2)));
            value = tmp;
            --index;
            buf[index] = DigitOnes[digitOnesIndex]; // 余数的个位
            --index;
            buf[index] = DigitTens[digitOnesIndex]; // 余数的十位
        }

        // 处理中等数值
        int var1,var2;
        for(var2=(int)value;var2>=65536;){
            var1 = var2 / 100; // 得到除以100的高位部分
            digitOnesIndex = var2 - (var1 * 100); // 计算余数：var2-(var1*100)
            var2 = var1;
            --index;
            buf[index] = DigitOnes[digitOnesIndex]; // 余数的个位
            --index;
            buf[index] = DigitTens[digitOnesIndex]; // 余数的十位
        }

        // 处理小数值
        /*
        * '쳍' 的 Unicode 值为 49425，计算 (var10 * 49425) >>> 19 近似等于 var10 / 10
        * 49425 / 524288 (2^19) ≈ 0.09434，近似 1/10，通过整数运算避免除法开销
         */
        do {
            // 快速计算除以 10 的近似值：var9 = var10 / 10
            // '쳍' 的 Unicode 值为 49425，计算等价于 (var10 * 5243) >>> 19 ≈ var10 / 10
            var1 = var2 * '쳍' >>> 19;
            digitOnesIndex = var2 - ((var1 << 3) + (var1 << 1));
            --index;
            buf[index] = digits[digitOnesIndex];
            var2 = var1;
        } while(var1 != 0);

        if(var!=0){
            --index;
            buf[index] = var; // 符号位
        }
    }
}
